﻿#region Using

using System.Linq;
using System.Threading.Tasks;
using Vk.Methods.Common;
using Vk.Methods.Photos;
using Vk.Methods.Users;
using Vk.Methods.Wall;

#endregion

namespace Vk.Methods.Fave
{
    /// <summary>
    ///     Закладки
    /// </summary>
    public class Fave
    {
        private readonly Api _api;

        public Fave(Api api)
        {
            _api = api;
        }

        /// <summary>
        ///     Возвращает ссылки, добавленные в закладки текущим пользователем.
        /// </summary>
        public async Task<ListCount<LinkInfo>> GetLinks(int? count = null, int? offset = null)
        {
            var query = new ApiQuery("fave.getLinks")
                .Add("count", count)
                .Add("offset", offset);

            var result = await _api.Manager.Execute(query);

            if (_api.Manager.MethodSuccessed)
            {
                var nodes = result.SelectNodes("items/*");
                var countNode = result.SelectNode("count");
                if (nodes != null && countNode != null)
                {
                    return new ListCount<LinkInfo>(countNode.Int().Value,
                                                   nodes.Select(x => new LinkInfo(x)).ToList());
                }
            }
            return null;
        }

        /// <summary>
        ///     Возвращает фотографии, на которых текущий пользователь поставил отметку "Мне нравится".
        /// </summary>
        /// <param name="count">Количество фотографий, которое необходимо получить.</param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества фотографий.</param>
        public async Task<ListCount<Photo>> GetPhotos(int? count = null, int? offset = null, bool? photoSizes = null)
        {
            var query = new ApiQuery("fave.getPhotos")
                .Add("count", count)
                .Add("offset", offset)
                .Add("photo_sizes", photoSizes);

            var result = await _api.Manager.Execute(query);

            if (_api.Manager.MethodSuccessed)
            {
                var nodes = result.SelectNodes("items/*");
                var countNode = result.SelectNode("count");
                if (nodes != null && countNode != null)
                {
                    return new ListCount<Photo>(countNode.Int().Value,
                                                nodes
                                                    .Select(x => new Photo(x))
                                                    .ToList());
                }
            }
            return null;
        }

        /// <summary>
        ///     Возвращает записи, на которых текущий пользователь поставил отметку "Мне нравится".
        /// </summary>
        /// <param name="count">Количество сообщений, которое необходимо получить (но не более 100).</param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества сообщений.</param>
        /// <param name="extended">
        ///     true — в ответе будут возвращены дополнительные поля profiles и groups, содержащие информацию о
        ///     пользователях и сообществах. По умолчанию: false.
        /// </param>
        public async Task<ItemsCountProfilesGroups<WallPost>> GetPosts(int? count = null,
                                                                         int? offset = null,
                                                                         bool? extended = null)
        {
            var query = new ApiQuery("fave.getPosts")
                .Add("count", count)
                .Add("offset", offset)
                .Add("extended", extended);

            var result = await _api.Manager.Execute(query);

            return _api.Manager.MethodSuccessed
                       ? new ItemsCountProfilesGroups<WallPost>(result, node => new WallPost(node))
                       : null;
        }

        /// <summary>
        ///     Возвращает список пользователей, добавленных текущим пользователем в закладки
        /// </summary>
        /// <param name="count">Количество пользователей, информацию о которых необходимо вернуть</param>
        /// <param name="offset">Смещение, необходимое для выборки определенного подмножества пользователей. По умолчанию — 0</param>
        public async Task<ListCount<BaseUser>> GetUsers(int? count = null, int? offset = null)
        {
            var query = new ApiQuery("fave.getUsers")
                .Add("count", count)
                .Add("offset", offset);

            var result = await _api.Manager.Execute(query);
            if (_api.Manager.MethodSuccessed)
            {
                var nodes = result.SelectNodes("items/*");
                if (nodes != null && count != null)
                {
                    return new ListCount<BaseUser>(result.Int("count").Value,
                                                   nodes.Select(x => new BaseUser(x)).ToList());
                }
            }
            return null;
        }

        /// <summary>
        ///     Возвращает список видеозаписей, на которых текущий пользователь поставил отметку "Мне нравится".
        /// </summary>
        /// <param name="count">Количество возвращаемых видеозаписей.</param>
        /// <param name="offset">Смещение относительно первой найденной видеозаписи для выборки определенного подмножества.</param>
        /// <param name="extended">
        ///     true — в ответе будут возвращены дополнительные поля profiles и groups, содержащие информацию о
        ///     пользователях и сообществах. По умолчанию: false.
        /// </param>
        public async Task<ItemsCountProfilesGroups<Video.Video>> GetVideos(int? count = null,
                                                                           int? offset = null,
                                                                           bool? extended = null)
        {
            var query = new ApiQuery("fave.getVideos")
                .Add("count", count)
                .Add("offset", offset)
                .Add("extended", extended);

            var result = await _api.Manager.Execute(query);

            return _api.Manager.MethodSuccessed
                       ? new ItemsCountProfilesGroups<Video.Video>(result, node => new Video.Video(node))
                       : null;
        }
    }
}